home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 22 / Cream of the Crop 22.iso / program / cgazv4n3.zip / FILES.C < prev    next >
C/C++ Source or Header  |  1990-02-06  |  7KB  |  294 lines

  1. /******************************  FILES.C  *******************************
  2.  * Author: John Rex
  3.  * Date: October, 1989
  4.  * Compilers: MSC 5.1
  5.  *            Turbo C 2.0
  6.  * Operating Systems: DOS and OS/2
  7.  * Memory Models: any
  8.  * Purpose: file name manipulation routines:
  9.  *          normal_name() - normalizes a partial file name to one with
  10.  *                          drive and correct path (all \.. stuff removed)
  11.  *          add_ext()     - add a file extension
  12.  *          del_ext()     - delete file extension
  13.  *
  14.  * Compile time switches: TEST brings in a test driver
  15.  *                        OS2  to get OS/2 compile (MSC only)
  16.  *
  17.  * Sample OS/2 compile lines:
  18.  *  OS/2 only version: cl /G2 /DOS2 /Lp /DTEST files.c
  19.  *  OS/2 or DOS (bound): cl /G2 /DOS2 /Lp /DTEST files.c /Fbbfiles.exe
  20.  *
  21.  * Source code may be freely used if authorship is acknowledged
  22.  * Object code may be freely used
  23.  **********************************************************************/
  24.  
  25. #include <stdio.h>
  26. #include <ctype.h>
  27. #include <string.h>
  28. #include <stdlib.h>
  29.  
  30. #if !defined (OS2)              /* DOS only stuff */
  31. #include <dos.h>
  32.  
  33. /* define our own versions to avoid bugs with MSC's versions */
  34. #define FP_GETOFF(p)  ((unsigned) (p))
  35. #define FP_GETSEG(p)  ((unsigned) ((unsigned long)(p) >> 16) )
  36.  
  37. union  REGS  dataregs;
  38. struct SREGS segregs;
  39.  
  40. #define _rax        dataregs.x.ax
  41. #define _rdx        dataregs.x.dx
  42. #define _rsi        dataregs.x.si
  43. #define _rds        segregs.ds
  44. #define _carryf        dataregs.x.cflag
  45. #define _doint(x)   int86x(x,&dataregs,&dataregs,&segregs)
  46.  
  47. #define DOS_CALL        0x21
  48. #define GET_DEF_DRIVE    0x1900
  49. #define GET_DIR            0x4700
  50.  
  51. #else                           /* OS/2 */
  52. #define INCL_DOS
  53. #define INCL_NOPM               /* save time - no PM stuff */
  54. #include <os2.h>
  55. #endif
  56.  
  57. int def_drive(void), get_directory(int, char *);
  58.  
  59. /* the character we use to delimit subdirs in final product */
  60. #define delim   '/'
  61.  
  62. char *normal_name(char *file, char *buffer)
  63.     /* given a filename of the form
  64.  
  65.         [d:][path or partial path]filename
  66.  
  67.        normal_name() will return a pointer to a string containing the fully
  68.        expanded path to the file.  The partial path may use / or \ and it
  69.        may use the .. operator for backup in a directory tree.  NULL is
  70.        returned if the path parse fails.  The var buffer is used as the work
  71.        area - the returned pointer will be to buffer (if it's not a NULL).
  72.     */
  73.  
  74. {
  75.     char path[100];
  76.     char *p, *s, save;
  77.     int drive;
  78.  
  79.     /* first convert all \ & / to one style */
  80.     for (p = file; *p != '\0'; p++)
  81.         if (*p == '/')
  82.             *p = '\\';
  83.  
  84.     /* are we given a drive? */
  85.     if ((p = strchr(file, ':')) != NULL) {
  86.         if (p - file != 1)
  87.             return(NULL);    /* error */
  88.  
  89.         drive = tolower(file[0]) - 'a';
  90.         file += 2;
  91.     }
  92.     else
  93.         drive = def_drive();
  94.  
  95.     if (get_directory(drive, path + 1) == 0)
  96.         return(NULL);
  97.     path[0] = '\\';      /* DOS doesn't supply the leading \ */
  98.  
  99.     /* now, march thru given file name and append to path */
  100.  
  101.     /* if filename starts with '\', then must go back to root */
  102.     if (*file == '\\') {
  103.         path[1] = '\0'; /* set path to just a root */
  104.         file++;
  105.     }
  106.  
  107.     /* path should always end in \ */
  108.     if (path[strlen(path) - 1] != '\\')
  109.         strcat(path, "\\");
  110.  
  111.     /* now, look at each subdir in filename */
  112.     while((p = strchr(file, '\\')) != NULL) {
  113.         save = *++p;
  114.         *p = '\0';
  115.         if (file[0] == '.') { /* look at dot operator */
  116.             if (strcmp(file ,"..\\") == 0) { /* back up one subdir */
  117.                 s = strrchr(path, '\\'); /* find start of previous subdir */
  118.                 if (s == path)
  119.                     s++;
  120.                 else {
  121.                     *s = '\0';    /* remove trailing \ */
  122.                     s = strrchr(path, '\\') + 1; /* find preceeding \ */
  123.                 }
  124.  
  125.                 *s = '\0';
  126.             }
  127.             else
  128.                 ; /* ignore other . commands */
  129.         }
  130.         else /* a subdir name */
  131.             strcat(path, file);
  132.  
  133.         *p = save;
  134.         file = p;
  135.     }
  136.  
  137.     /* and append the file name */
  138.     strcat(path, file);
  139.  
  140.     /* return the fruit of our labors */
  141.     p = buffer;
  142.     p[0] = (char) ('a' + drive);
  143.     p[1] = '\0';
  144.     strcat(p, ":");
  145.     strcat(p, path);
  146.     for (s = p; *s != '\0'; s++) /* convert delimiters to final form */
  147.         if (*s == '\\')
  148.             *s = delim;
  149.         else
  150.             *s = (char) tolower(*s);
  151.  
  152.     return(p);
  153. }
  154.  
  155. static struct d_list {  /* a place to keep a list of things we've looked up */
  156.     int drive;
  157.     char *dir;
  158.     struct d_list *next;
  159. } *d_head = NULL;
  160.  
  161. int def_drive() /* return current default drive. 0 = A, 1 = B, etc. */
  162. {
  163. #if !defined (OS2)
  164.     _rax = GET_DEF_DRIVE;
  165.     _doint(DOS_CALL);
  166.     return(_rax & 0xFF);
  167.  
  168. #else
  169.     USHORT usDriveNumber;
  170.     ULONG ulLogicalDrives;
  171.     DosQCurDisk(&usDriveNumber, &ulLogicalDrives);
  172.     return(usDriveNumber - 1);
  173. #endif
  174. }
  175.  
  176. int get_directory(drive, buffer) /* get current directory for drive */
  177. int drive;    /* 0 = A, 1 = B, etc. */
  178. char *buffer;    /* put result here */
  179. {
  180.     struct d_list *d_ptr;
  181.  
  182. #if defined(OS2)
  183.     USHORT cbPath;
  184. #endif
  185.  
  186.     /* do we already know this one? */
  187.     for (d_ptr = d_head; d_ptr != NULL; d_ptr = d_ptr -> next)
  188.         if (d_ptr -> drive == drive) { /* found it */
  189.             strcpy(buffer, d_ptr -> dir);
  190.             return(1);
  191.         }
  192.  
  193.     /* haven't looked this one up - find out about it */
  194. #if !defined(OS2)
  195.     buffer[0] = '\0';    /* terminate the buffer */
  196.     _rax = GET_DIR;
  197.     _rdx = (unsigned) (drive + 1);
  198.     _rds = FP_GETSEG((void far *) buffer);
  199.     _rsi = FP_GETOFF((void far *) buffer);
  200.  
  201.     _doint(DOS_CALL);
  202.  
  203.     if (_carryf)
  204.         return(0);    /* something went wrong */
  205.  
  206. #else /* OS/2 */
  207.     if (DosQCurDir(drive+1, buffer, &cbPath))
  208.         return (0); /* something went wrong */
  209. #endif
  210.  
  211.     else {     /* success */
  212.         /* store a copy of what we found */
  213.         d_ptr = (struct d_list *) malloc(sizeof(struct d_list));
  214.         d_ptr -> next = d_head;
  215.         d_head = d_ptr;
  216.         d_ptr -> drive = drive;
  217.         d_ptr -> dir = malloc((unsigned) (strlen(buffer) + 1));
  218.         strcpy(d_ptr -> dir, buffer);
  219.  
  220.         /* and return */
  221.         return(1);
  222.     }
  223. }
  224.  
  225.  
  226. /* routines to add or remove file extensions */
  227. char *last_dot(char *file)    /* find the dot of the file.ext portion of a filename */
  228. {
  229.     char *s;
  230.  
  231.     if      ((s = strrchr(file, '/' )) != NULL) ;
  232.     else if ((s = strrchr(file, '\\')) != NULL) ;
  233.     else s = file;
  234.  
  235.     return(strrchr(s, '.'));
  236. }
  237.  
  238. void delext(file)    /* remove the extension from a file name */
  239. char *file;
  240. {
  241.     char *s;
  242.  
  243.     s = last_dot(file);
  244.     if (s != NULL)
  245.         *s = '\0';
  246. }
  247.  
  248. void addext(file, ext)    /* add an extension unless one is already present */
  249. char *file;
  250. char *ext;
  251. {
  252.     char *s;
  253.  
  254.     s = last_dot(file);
  255.     if (s == NULL) {
  256.         strcat(file, ".");
  257.         strcat(file, ext);
  258.     }
  259. }
  260.  
  261. #ifdef TEST                /* If defined, run the test driver */
  262. int cdecl main(argc, argv)
  263. int argc;
  264. char **argv;
  265. {
  266.     char *s, buf[100], work[100];
  267.  
  268.     if (argc < 2)
  269.         puts("Syntax is: files file_1 file_2 ...\n");
  270.     else {
  271.         argc--;
  272.         argv++;
  273.         while(argc--) {
  274.             strcpy(buf, *argv++);
  275.             puts(buf);
  276.             puts(" is altered to ");
  277.             delext(buf);
  278.             addext(buf, "zzz");
  279.             puts(buf);
  280.             puts("\n");
  281.  
  282.             s = normal_name(buf, work);
  283.             puts(buf);
  284.             puts(" becomes ");
  285.             if (s != NULL)
  286.                 puts(s);
  287.             else
  288.                 puts("path parse failed");
  289.             puts("\n");
  290.             puts("\n");
  291.         }
  292.     }
  293. }
  294. #endif